Skip to content

v1 emitter: extend Clone-bound WF propagation to FN/IMPL emission - #7708

Merged
briansrls merged 4 commits into
mainfrom
session/loyal-lynx-332
Aug 3, 2026
Merged

briansrls merged 4 commits into
mainfrom
session/loyal-lynx-332

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Aug 2, 2026 •

Copy link
Copy Markdown
Contributor

Worker attestation

  • Title describes the change (not the session id or branch).
  • PR body summarises what and why.
  • Tests run: named below.
  • No commits on this branch are surprises.
  • No secrets / credentials / large binaries staged.

Summary

Follow-up to #7691: extends v1's Clone-bound well-formedness propagation from struct/enum items to fn declarations and fixes a second, related bug in impl-header emission for enum shared accessors, both discovered live in deep-heron's honest regen of dag/std/occurrence_binding.dag.

Two distinct bugs, one root mechanism:

  1. E0277 (bare fn generics). A fn naming a Clone-WF-bounded declared type in a value-param or return-type position (e.g. occurrence_binding_from_candidates<N>(occurrence: BindingOccurrence<N>, ...) -> OccurrenceBindingResult<N>) needs N: Clone for the same reason a struct field does, but the fn path never checked it. Root cause was a raw-root/resolved-children inconsistency: the fn-path WF check uses the raw (un-typechecked) top-level param type_expr (needed because the typechecked node loses ident_span for fn params specifically), but three downstream recursive helpers resolved nested children via child_type_node, which loses ident_span again — a mismatch specific to the fn path (the struct/enum path is unaffected because it's raw-or-resolved consistently top-to-bottom). Fixed with one shared fallback helper, v1_wf_child_type_node: try the resolved node, fall back to the raw child only when the resolved node's name is empty. This is a single-authority fix, not a forked predicate, but it is not confined to the fn path: the three call sites it replaces (v1_type_expr_clone_impl_needs_param, v1_declared_arg_positions_need_clone_param, v1_type_expr_wf_needs_clone_param) are shared helpers also reached from the item path via v1_item_param_wf_needs_clone, so struct/enum recursion now runs through the same fallback too. What is unchanged is the item path's output, not its code path — the fallback is a no-op there because struct/enum resolved children always carry a non-empty authored name. That is an invariant, not a re-derivation: the evidence for it is the nine pre-existing item witnesses still passing unchanged plus deep-heron's 58-to-0 production regen (below), not a proof that the invariant must hold for every shape.

  2. E0229 (impl-header bound repetition), found while writing the witness for (1). emit_enum_shared_accessors rendered impl<N: Clone> Foo<N: Clone> { ... } — the Clone-bounded type_params string (with bounds, correct for the impl<...> declaration position) was reused verbatim for the type-application position (Foo<...>), where a bound on a type argument is invalid Rust. Added emit_bare_type_params to render the name-only form for the type-application position; the declaration position keeps the bounded string.

Dual-representation audit (per review request): neither fix re-derives Clone-bound facts independently. The fn-grain check reuses v1_type_expr_wf_needs_clone_param verbatim against the same emit_info.clone_bounded_type_params — the single item-level fixpoint result computed once per compile by v1_clone_bound_fixpoint_loop (landed in #7691). The fn path runs no fixpoint and holds no bounds map of its own; it only asks the existing authority a WF question at a new call site (fn params/return, the "third site" alongside struct fields and enum-coproduct fields). The impl-header fix touches only string rendering (which positions get the bounds string vs. the bare-names string) — it does not touch bound computation at all.

Availability note: Codex is out until Aug 8; this PR is unreviewed by that provider in the interim.

Test plan

  • cargo run --manifest-path src/v1/stage0/Cargo.toml --bin regen_stage0 — clean regen, 113 files, no diff beyond the intended .dag source changes reflected.
  • cargo run --manifest-path src/v1/stage0/Cargo.toml --bin claim_batch -- --source-root dag --source-root src/v2 --entry dag/test/claim/generic_item_clone_bound_witness_test.dag --functions fn_wf_bound_propagation_positive,fn_wf_no_trigger_negative_control,impl_accessor_inherits_item_bound_once,containment_path_clone_bound_positive,unused_generic_param_negative_control,both_triggers_render_single_bound,declared_generic_type_propagation_positive,coproduct_well_formedness_propagation_positive,coproduct_bare_payload_negative_control,unbounded_declared_generic_negative_control,recursive_declared_type_saturation_positive,unbounded_declared_container_negative_control — all 12 witnesses (3 new + 9 pre-existing) PASS, exit 0. The 3 new witnesses are RED-on-pre-fix/GREEN-on-fix, executed both directions: confirmed FAIL before the fix (fn path unbounded / impl header double-bound) and PASS after.
  • Direct specimen check: gunbc compile --source-root dag --entry dag/std/occurrence_binding.dag --target rust now emits pub fn occurrence_binding_from_candidates<N: Clone>(...) and impl<N: Clone> OccurrenceBindingFoldState<N> { (previously <N> bare and impl<N: Clone> OccurrenceBindingFoldState<N: Clone> respectively).
  • Acceptance oracle, run by deep-heron-234 against this PR's exact head a283ebdc3eda062096e4606e773cfd78dabd772c (stale-binary discipline: fresh regen_stage0 binary rebuilt from that head, never a reused committed binary): worktree at a283ebdc3ed → rebuilt regen_stage0 from that tree → emitted occurrence_binding + candidates/resolve/parser_walk/witness from deep-heron's B1 authored sources with that binary → installed the emit into the real v1-compiler stage0 crate → cargo check -p v1-compiler. Prior Propagate item Clone bounds as a fixpoint over the declared-type graph #7691-residual class was 58 errors (E0229 double-bound impl + E0277 bare fn generics); after this PR's emit, 0 errors, clean Finished, with the specimens confirmed correct: impl<N: Clone> OccurrenceBindingFoldState<N> (no double bound) and occurrence_binding_from_candidates<N: Clone>(...). No residual Clone-emit error class found; no third emitter PR needed for this gap.

Owed follow-up (not a blocker for this PR): coverage of v1_wf_child_type_node is asymmetric. The fires-branch (resolved child empty, raw child used) is discriminatingly witnessed by w_fn_wf_bound_propagates_to_bare_generic. The no-op branch (resolved child non-empty, taken on the item path) is covered only indirectly — the nine pre-existing item witnesses continue to pass, but nothing in the suite would necessarily red if the fallback wrongly fired on an item, since taking the raw child yields the right answer for many shapes anyway. A witness that discriminates the two arms directly belongs in a follow-up PR, where it costs nothing to add; extracting it here would restale both approvals and cost another CI cycle for something the production oracle already exercises in practice.

gunbai-bot Bot pushed a commit that referenced this pull request Aug 2, 2026
CI auto-heal pulled std.occurrence_binding* into stage0 before #7515/#7708
fn Clone emit lands — emitted Rust did not compile. PR-A is dag authority +
witnesses only; remove src/v1 production stub that entered regen closure.
Restore stage0 + emit plan to main; regen_stage0 --verify divergence_count=0.

Co-authored-by: Cursor <cursoragent@cursor.com>
gunbai-bot Bot pushed a commit that referenced this pull request Aug 3, 2026
CI auto-heal pulled std.occurrence_binding* into stage0 before #7515/#7708
fn Clone emit lands — emitted Rust did not compile. PR-A is dag authority +
witnesses only; remove src/v1 production stub that entered regen closure.
Restore stage0 + emit plan to main; regen_stage0 --verify divergence_count=0.

Co-authored-by: Cursor <cursoragent@cursor.com>
emit_enum_shared_accessors rendered `impl<N: Clone> Foo<N: Clone>` --
the Clone-bounded type_params string was reused for both the impl
generic-param declaration (correct) and the type-application position
(invalid Rust: a bound cannot be repeated on a type argument). Added
emit_bare_type_params to render the name-only form for the type
application, leaving type_params (with bounds) for the impl<...>
declaration.

Extends witness coverage in generic_item_clone_bound_witness_test.dag:
the fn-grain WF witnesses now declare their generic params explicitly
(fn foo<N>(...)), matching how v1 fn generics are actually introduced
(unlike struct/enum fields, a fn's type params are not inferred from
usage), and the impl-accessor witness now exercises an enum with a
shared field across fielded variants -- the actual shape that reaches
emit_enum_shared_accessors -- rather than a plain struct, which never
reaches that emitter path. All three new witnesses and all nine
pre-existing witnesses in the file pass by execution; the real
dag/std/occurrence_binding.dag specimen emits
`occurrence_binding_from_candidates<N: Clone>` and
`impl<N: Clone> OccurrenceBindingFoldState<N> {` correctly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@gunbai-bot gunbai-bot Bot changed the title CRITICAL PATH v1 emitter follow-up to #7691 (merged 7ef7206a8e): extend Clone-bound propagation to FN/IMPL emission. Item-level fixpoint (v1_clone_bound_fixpoint_loop, EmitGraphInfo.clone_bounded_type_params) works; two live specimens from deep-heron's honest regen of dag/std/occurrence_binding.dag v1 emitter: extend Clone-bound WF propagation to FN/IMPL emission Aug 3, 2026
@gunbai-bot
gunbai-bot Bot marked this pull request as ready for review August 3, 2026 00:27
@briansrls
briansrls merged commit 4971517 into main Aug 3, 2026
5 of 10 checks passed
@briansrls
briansrls deleted the session/loyal-lynx-332 branch August 3, 2026 01:42
gunbai-bot Bot pushed a commit that referenced this pull request Aug 3, 2026
Pull #7708 Clone fn/impl emit fix so B1 occurrence-binding seed can enroll honestly.
gunbai-bot Bot pushed a commit that referenced this pull request Aug 3, 2026
Honest regen from merged sources (fresh regen_stage0): production specimen
cargo-checks green with correct fn/impl Clone bounds; no http_path AuthoredTokenOrdinal leak.

Co-authored-by: Cursor <cursoragent@cursor.com>
briansrls pushed a commit that referenced this pull request Aug 3, 2026
* N2 slice 2 PR-A: TypeReferenceBindingContext + P2 input builder

Land the graph-wide OccurrenceBindingCandidateInputs projector and
TypeReferenceBindingContext carrier per quiet-hawk-219 PR-A scope:
containment-tree exposure derivation (RootExposure at module-root,
Module/Lexical otherwise), multi-module merge, and five executing
fixture witnesses. v1 ModuleGraph adapter is a thin PR-B stub only;
no stage0 enrollment and no resolve_node_bounded wiring until 7515.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Document resolve-only path scope for N2 slice-2 claims

Per quiet-hawk-219: containment binding closes pool-membership coincidence
on the RESOLVE path only; emit-side item_registry leaf-key collision
(#7685/#7705) is a separate surviving instance explicitly out of slice.

Co-authored-by: Cursor <cursoragent@cursor.com>

* chore: regenerate drifted generated artifacts (ci auto-heal)

* Correct emit-side scope: LIVE instance with RED #7705 control

#7685 did not repair cross-module same-leaf emit collision; #7705
detector is RED on main (bottom rung). Cite warm-wolf-814 ownership;
name as separate live instance, not guarded. Add PR-B motivation note.

Co-authored-by: Cursor <cursoragent@cursor.com>

* WIP: N2 slice 2 (import-deletion program): FIRST TypeReference PRODUCTION con

* Revert premature stage0 regen; defer production stub to PR-B

CI auto-heal pulled std.occurrence_binding* into stage0 before #7515/#7708
fn Clone emit lands — emitted Rust did not compile. PR-A is dag authority +
witnesses only; remove src/v1 production stub that entered regen closure.
Restore stage0 + emit plan to main; regen_stage0 --verify divergence_count=0.

Co-authored-by: Cursor <cursoragent@cursor.com>

* WIP: N2 slice 2 (import-deletion program): FIRST TypeReference PRODUCTION con

* Fix lexical exposure witness: compare OccurrenceId, not Int.

nested_containment_derives_lexical_exposure_holds compared
scope.terminal.value to an OccurrenceId binding, which always
evaluated false at runtime and failed CI batch 3.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
gunbai-bot Bot pushed a commit that referenced this pull request Aug 3, 2026
Integrate #7708 fn-level WF propagation (ret + v1_wf_child_type_node) with
the keyed-carrier scaffold and structural derivation helpers; regen stage0
to converge after the merge.

Co-authored-by: Cursor <cursoragent@cursor.com>
briansrls pushed a commit that referenced this pull request Aug 3, 2026
* slice-B: parser occurrence-role + structural binding walk bridge

Recut #7515 on main after slice A: stamp CallableOccurrence from ExprCall /
fn-body NoExprData, derive exposure/order from parser transport, and carry
exact index refusals through StructuralBindingWalkRefused. Stage0 enrollment
of binding/resolve held pending jolly-lynx-242 Clone-bound emitter fix.

Co-authored-by: Cursor <cursoragent@cursor.com>

* slice-B1: fix parser-walk exposure + greeter edge assertions

LexicalExposure terminal is the nearest containment parent of the
reference (not root ancestor, not binder-as-own-path). Greeter cases
assert per-reference Bound providers and zero M→M DirectModuleDependency
edges (slice A skips same-module self-edges). Pattern-arm binder nesting
parked with dissolve-on until the parser nests arm bodies under binders.
Offline rollup namespace_reference_derived_closure_parser_integration_holds PASS.

Co-authored-by: Cursor <cursoragent@cursor.com>

* slice-B1: register parser-walk emit outputs for regen fixed-point

Regen refused five unregistered stage0 files pulled in by the B1 bridge
closure. Enroll them in generated_stage0_files, commit the emitted seed
(including lib.rs mods), and refresh sibling Clone-bound emit drift so
regen_stage0 --verify stays at divergence 0. cargo check -p v1-compiler green.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Revert false stage0 enrollment from a stale regen binary

644512e committed Clone-bound seed bytes a rebuilt narrow-only
regen_stage0 does not produce (BindingOccurrence chain stays bare;
24x E0277 under honest emit). A ready PR must not carry a fabricated
fixed-point. Re-enroll only after #7691 lands on main: merge main,
rebuild regen from merged sources, regenerate once.

Co-authored-by: Cursor <cursoragent@cursor.com>

* chore: regenerate drifted generated artifacts (ci auto-heal)

* Enroll B1 occurrence-binding stage0 seed after #7708 Clone emit fix.

Honest regen from merged sources (fresh regen_stage0): production specimen
cargo-checks green with correct fn/impl Clone bounds; no http_path AuthoredTokenOrdinal leak.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Regenerate ci.yml after B1 stage0 enrollment (HealAuthorCommitRequired).

main_wet: heal conflict-exclude list now covers the enrolled occurrence_binding seed modules; GitHub App cannot push workflow writes.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
gunbai-bot Bot pushed a commit that referenced this pull request Aug 3, 2026
#7709 (9bed216) regenerated v1_compiler_emit_rust.rs from a base predating
#7708 (4971517), silently reverting both of #7708's fixes while keeping the
matching .dag sources. Git saw no conflict because only one side edited the file.

Lost and restored here, by regen from current main .dag sources:
- v1_generic_params_needing_clone_bound call site: 3 arguments (inferred,
  emit_info.clone_bounded_type_params, emit_info.type_decl_items) against a
  9-parameter signature -> E0061, v1-compiler lib did not compile.
- emit_bare_type_params + its use in emit_enum_shared_accessors -> the E0229
  impl-header fix, which regen showed was also lost.

#7709's own qualified-registry work is untouched.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
briansrls added a commit that referenced this pull request Aug 3, 2026
…en (#7733)

* WIP: namespace migration (import deletion)

* Repair main: restore #7708 emitter fixes lost to #7709 stale seed

#7709 (9bed216) regenerated v1_compiler_emit_rust.rs from a base predating
#7708 (4971517), silently reverting both of #7708's fixes while keeping the
matching .dag sources. Git saw no conflict because only one side edited the file.

Lost and restored here, by regen from current main .dag sources:
- v1_generic_params_needing_clone_bound call site: 3 arguments (inferred,
  emit_info.clone_bounded_type_params, emit_info.type_decl_items) against a
  9-parameter signature -> E0061, v1-compiler lib did not compile.
- emit_bare_type_params + its use in emit_enum_shared_accessors -> the E0229
  impl-header fix, which regen showed was also lost.

#7709's own qualified-registry work is untouched.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Brian Searls <briansearls1@gmail.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
gunbai-bot Bot pushed a commit that referenced this pull request Aug 3, 2026
Regen failed: seed lagged the restored emitter (#7708 via #7733). Drop the
temporary 3-line E0061 carry in favor of main's fixed-point seed.

Co-authored-by: Cursor <cursoragent@cursor.com>
briansrls pushed a commit that referenced this pull request Aug 3, 2026
* docs: register floor prep-tax program (retention-first CI wall)

Anchors the ~2s/entry setup diagnosis and binding P1–P4 order so
selection honesty, width-2, and native expansion cannot outrun amortized prep.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs: clarify prep-tax gates vs five-minute native cutover

Address review 47719: P1 gates width and broad native enrollment only,
not five-minute step 3's bounded cohort. Fold P3 conjunction (P1 +
index share / Rc→Arc) with the measured width-latch receipts, and bank
the claim_batch retain-all lower bound from the #7597 50-entry harness.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs: retract #7597 Mode-B prior from prep-tax P1 framing

P1 must discriminate on the armed floor A/B receipt. Additive harness
shares are a different denominator, unarmed ≠ Mode B, and #7597 forbids
mechanism selection from those prices.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(docs): bind floor-prep-tax-program in doc graph

Unbound hand-authored plan was an orphan under doc_graph_has_no_orphan_docs
and blocked #7721 CI; enroll HandAuthoredDocBind and link from five-minute.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs: park floor prep-tax program with pickup snapshot

Record P1 REJECT / open PR heads / HOLD leaves and ordered resume steps
before operator pause; no further dispatch this stretch.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs: note closeout #7731 closed in park snapshot

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(docs): drop dangling P1 receipt link until #7725 merges

doc_graph_has_no_dangling_links reds a relative link to a file that
exists only on the P1 branch; cite the path/PR in prose instead.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs: correct #7725 CI block — main E0061, not leaf

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: restore 9-arg clone-bound call (main tip E0061)

Same three-arg restore as #7734 — main's merge-ref fails the build gate
on a stale 6-arg site. Temporary carry until #7733/#7734 land on main;
dissolves when main is green.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: align stage0 emit_rust with main after #7733

Regen failed: seed lagged the restored emitter (#7708 via #7733). Drop the
temporary 3-line E0061 carry in favor of main's fixed-point seed.

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs: bank P1 REJECT on #7725 in park snapshot

Co-authored-by: Cursor <cursoragent@cursor.com>

* docs: mark #7722 P2 merge-ready in park snapshot

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant